﻿#include "pch.h"

AnalysisPool *gAnalPoolList = NULL;
int32_t *gChannelOpened = NULL;
int32_t *gChannelBusy = NULL;

TSMPBAG *old_smpBag[100];
TDLLIPINF *old_ipInf[100];
TDLLEPINF *old_epInf[100];
TDLLIDTINF *old_idtInf[100];
TDLLRESINF *old_resInf[100];
TDLLSTDINF *old_stdInf[100];

char aAnalysisDll[13] = "analysis.dll";
void (*fnDrawTickMark)(int32_t, int32_t, TICKMARK) = NULL; // weak

// sub_1001D700
AnalysisPool::AnalysisPool()
{
    pAnalExecutor = NULL;
    pTsmpBag = NULL;
    pIParaWrapper = NULL;
    pTprgInfWrapper = NULL;
    pResInfWrapper = NULL;
    pEParaWrapper = NULL;
    pGrpInfWrapper = NULL;
    pIdtInfWrapper = NULL;
    pAmtInfWrapper = NULL;
    pCptInfWrapper = NULL;
    pStdInfManager = NULL;
    isOpened = false;
    isStarted = false;
};

void AnalysisPool::printSelf(char *captionUpper, int32_t deep)
{
    char caption[1024];
    sprintf(caption, "%s:%s", captionUpper, "AnalysisPool");
    print4x(this, sizeof(AnalysisPool), caption);
    if (--deep >= 0)
    {
        if (this->pAnalExecutor)
        {
            this->pAnalExecutor->printSelf(caption, deep);
        }
        if (this->pTsmpBag)
        {
            this->pTsmpBag->printSelf(caption, deep);
        }
        if (this->pIParaWrapper)
        {
            this->pIParaWrapper->printSelf(caption, deep);
        }
        if (this->pTprgInfWrapper)
        {
            this->pTprgInfWrapper->printSelf(caption, deep);
        }
        if (this->pResInfWrapper)
        {
            this->pResInfWrapper->printSelf(caption, deep);
        }
        if (this->pEParaWrapper)
        {
            this->pEParaWrapper->printSelf(caption, deep);
        }
        if (this->pGrpInfWrapper)
        {
            this->pGrpInfWrapper->printSelf(caption, deep);
        }
        if (this->pIdtInfWrapper)
        {
            this->pIdtInfWrapper->printSelf(caption, deep);
        }
        if (this->pAmtInfWrapper)
        {
            this->pAmtInfWrapper->printSelf(caption, deep);
        }
        if (this->pCptInfWrapper)
        {
            this->pCptInfWrapper->printSelf(caption, deep);
        }
        if (this->pStdInfManager)
        {
            this->pStdInfManager->printSelf(caption, deep);
        }
    }
}

// sub_10016B76
int32_t AnalysisPool::startAnal()
{
    if (!this->pAnalExecutor || !this->isOpened)
    {
        return 0;
    }
    this->isStarted = this->pAnalExecutor->start();
    return this->isStarted;
}
// sub_10016401
int32_t AnalysisPool::openAnal(TSMPBAG *smpBag, TDLLIPINF *ipInf, TDLLEPINF *epInf, TDLLIDTINF *idtInf,
                               TDLLRESINF *resInf, TDLLSTDINF *stdInf)
{
    CTsmpBag *pTsmpBagTemp;
    CTsmpBag *pTsmpBag;
    CIParaWrapper *pIParaWrapperTemp;
    CIParaWrapper *pIParaWrapper;
    CTprgInfWrapper *pTprgInfWrapperTemp;
    CTprgInfWrapper *pTprgInfWrapper;
    CEParaWrapper *pEParaWrapperTemp;
    CEParaWrapper *pEParaWrapper;
    CGrpInfWrapper *pGrpInfWrapperTemp;
    CGrpInfWrapper *pGrpInfWrapper;
    CIdtInfWrapper *pIdtInfWrapperTemp;
    CIdtInfWrapper *pIdtInfWrapper;
    CResInfWrapper *pResInfWrapperTemp;
    CResInfWrapper *pResInfWrapper;
    CAmtInfWrapper *pAmtInfWrapperTemp;
    CAmtInfWrapper *pAmtInfWrapper;
    CCptInfWrapper *pCptInfWrapperTemp;
    CCptInfWrapper *pCptInfWrapper;
    CStdInfManager *pStdInfWrapperTemp;
    CStdInfManager *pStdInfManager;
    AnalExecutor *pAnalExecutorTemp;
    AnalExecutor *pAnalExecutor;

    memset((void *)&gMakeIPara, 0, sizeof(AUTOIPARA));
    memset((void *)&gLearnIPara, 0, sizeof(AUTOIPARA));

    if (this->pAnalExecutor)
    {
        return false;
    }

    pTsmpBagTemp = new CTsmpBag();
    if (pTsmpBagTemp)
    {
        pTsmpBag = pTsmpBagTemp->init(smpBag); // sub_1001E6D0
    }
    else
    {
        pTsmpBag = NULL;
    }
    this->pTsmpBag = pTsmpBag;
    if (!pTsmpBag)
    {
        goto OPEN_FAILED;
    }

    pIParaWrapperTemp = new CIParaWrapper();
    pIParaWrapper = pIParaWrapperTemp ? pIParaWrapperTemp->init(ipInf->ipara) : NULL;
    this->pIParaWrapper = pIParaWrapper;
    if (!pIParaWrapper)
    {
        goto OPEN_FAILED;
    }

    pTprgInfWrapperTemp = new CTprgInfWrapper();
    pTprgInfWrapper = pTprgInfWrapperTemp ? pTprgInfWrapperTemp->init((TDLLTPRGINF *)ipInf->tprgInf) : NULL;
    this->pTprgInfWrapper = pTprgInfWrapper;
    if (!pTprgInfWrapper)
    {
        goto OPEN_FAILED;
    }

    pEParaWrapperTemp = new CEParaWrapper();
    pEParaWrapper = pEParaWrapperTemp ? pEParaWrapperTemp->init(epInf->epara) : NULL;
    this->pEParaWrapper = pEParaWrapper;
    if (!pEParaWrapper)
    {
        goto OPEN_FAILED;
    }

    if (epInf->grpInf)
    {
        pGrpInfWrapperTemp = new CGrpInfWrapper();
        pGrpInfWrapper = pGrpInfWrapperTemp ? pGrpInfWrapperTemp->init((TDLLTPRGINF *)epInf->grpInf) : NULL;
        this->pGrpInfWrapper = pGrpInfWrapper;
        if (!pGrpInfWrapper)
        {
        OPEN_FAILED:
            this->closeAnalPool();
            return false;
        }
    }
    else
    {
        this->pGrpInfWrapper = NULL;
    }

    pIdtInfWrapperTemp = new CIdtInfWrapper();
    pIdtInfWrapper = pIdtInfWrapperTemp ? pIdtInfWrapperTemp->init(idtInf) : NULL;
    this->pIdtInfWrapper = pIdtInfWrapper;
    if (!pIdtInfWrapper)
    {
        goto OPEN_FAILED;
    }

    pResInfWrapperTemp = new CResInfWrapper();
    pResInfWrapper = pResInfWrapperTemp ? pResInfWrapperTemp->init(resInf) : NULL;
    this->pResInfWrapper = pResInfWrapper;
    if (!pResInfWrapper)
    {
        goto OPEN_FAILED;
    }

    if (stdInf)
    {
        pAmtInfWrapperTemp = new CAmtInfWrapper();
        pAmtInfWrapper = pAmtInfWrapperTemp ? pAmtInfWrapperTemp->init(stdInf->amtInf) : NULL;
        this->pAmtInfWrapper = pAmtInfWrapper;
        if (!pAmtInfWrapper)
        {
            goto OPEN_FAILED;
        }

        pCptInfWrapperTemp = new CCptInfWrapper();
        pCptInfWrapper = pCptInfWrapperTemp ? pCptInfWrapperTemp->init(stdInf->cptInf) : NULL;
        this->pCptInfWrapper = pCptInfWrapper;
        if (!pCptInfWrapper)
        {
            goto OPEN_FAILED;
        }

        pStdInfWrapperTemp = new CStdInfManager();
        pStdInfManager = pStdInfWrapperTemp ? pStdInfWrapperTemp->init(this->pAmtInfWrapper, this->pCptInfWrapper,
                                                                       this->pEParaWrapper, this->pIdtInfWrapper,
                                                                       stdInf->CurveType, stdInf->Zero)
                                            : NULL;
        this->pStdInfManager = pStdInfManager;
        if (!pStdInfManager)
        {
            goto OPEN_FAILED;
        }
    }
    pAnalExecutorTemp = new AnalExecutor();
    pAnalExecutor = pAnalExecutorTemp
                        ? pAnalExecutorTemp->init(this->pTsmpBag, this->pIParaWrapper, this->pTprgInfWrapper,
                                                  this->pResInfWrapper, this->pEParaWrapper, this->pGrpInfWrapper,
                                                  this->pIdtInfWrapper, this->pStdInfManager)
                        : NULL;
    this->pAnalExecutor = pAnalExecutor;
    if (!pAnalExecutor)
    {
        goto OPEN_FAILED;
    }
    this->isOpened = true;
    this->isStarted = false;

    return true;
}

// sub_1001690E
int32_t AnalysisPool::closeAnal()
{
    if (!this->isOpened)
    {
        return false;
    }
    this->closeAnalPool();
    return true;
}

// sub_10016933
AnalysisPool *AnalysisPool::closeAnalPool()
{
    if (this->pTsmpBag)
    {
        delete this->pTsmpBag;
    }
    if (this->pIParaWrapper)
    {
        this->pIParaWrapper->close(1);
    }
    if (this->pTprgInfWrapper)
    {
        this->pTprgInfWrapper->close(1);
    }
    if (this->pResInfWrapper)
    {
        this->pResInfWrapper->close(1);
    }
    if (this->pEParaWrapper)
    {
        this->pEParaWrapper->close(1);
    }
    if (this->pGrpInfWrapper)
    {
        this->pGrpInfWrapper->close(1);
    }
    if (this->pIdtInfWrapper)
    {
        this->pIdtInfWrapper->close(1);
    }
    if (this->pAmtInfWrapper)
    {
        this->pAmtInfWrapper->close(1);
    }
    if (this->pCptInfWrapper)
    {
        this->pCptInfWrapper->close(1);
    }
    if (this->pStdInfManager)
    {
        this->pStdInfManager->close(1);
    }
    if (this->pAnalExecutor)
    {
        this->pAnalExecutor->close(1);
    }
    this->pAnalExecutor = NULL;
    this->isOpened = false;
    this->isStarted = false;

    return this;
}
// sub_10016CCC
char *AnalysisPool::getErrMsg()
{
    char *result;
    char *strTemp;

    // if ( Concurrency::details::SchedulerProxy::GetNumBorrowedCores(*this) != 4 )
    // return NULL;
    strTemp = this->pAnalExecutor->getErrMsg();
    if (*strTemp)
    {
        result = strTemp;
    }
    else
    {
        result = NULL;
    }
    return result;
}
// sub_10016BAC
int32_t AnalysisPool::stopAnal()
{
    int32_t flag;

    if (!this->pAnalExecutor || !this->isStarted)
    {
        return false;
    }
    flag = this->pAnalExecutor->stop();
    this->isStarted = false;
    this->pAnalExecutor->calcResultW50etc(0);
    this->pAnalExecutor->handlePrgItemEvent();
    return this->pAnalExecutor->setConcMetric() & flag;
}
// sub_10016C10
CODE AnalysisPool::execAnal()
{
    CODE execResult;

    if (!this->pAnalExecutor)
    {
        return ANAL_NOP;
    }
    if (this->pAnalExecutor->analInfo.code == ANAL_ERROR)
    {
        return ANAL_ERROR;
    }
    execResult = this->pAnalExecutor->execAnal();
    if (execResult == ANAL_STOP || execResult == ANAL_ERROR)
    {
        this->stopAnal();
    }
    return execResult;
}
// sub_1001D7C0
int32_t AnalysisPool::getAnalTime()
{
    int32_t analTime;

    if (this->isOpened)
    {
        analTime = this->pAnalExecutor->rawbagOffset;
    }
    else
    {
        analTime = 0;
    }
    return analTime;
}
// sub_10016C62
int32_t AnalysisPool::setStopTime(float stopTime)
{
    if (!this->pAnalExecutor || !this->isStarted)
    {
        return false;
    }
    this->pAnalExecutor->setStopTime(stopTime);
    return true;
}
// sub_10016C97
int32_t AnalysisPool::setPeakSmpHead(int32_t *pSmpHead)
{
    if (!this->pAnalExecutor || !this->isStarted)
    {
        return false;
    }
    this->pAnalExecutor->initRawBag(pSmpHead);
    return true;
}
int32_t InitAnalPool_(int32_t maxChannels, int32_t realChannels,
                      void(__cdecl *drawTickMark)(int32_t, int32_t, TICKMARK))
{
    int32_t result;
    // time_t Time;
    // struct tm *localTm;
    // int32_t year;
    // int32_t mon;
    // int32_t day;
    // int32_t nMaxChannels;
    // struct _finddata_t finddata;
    // int32_t tempBuffer[69];

    gMaxChannels = maxChannels;
    gMaxReal = realChannels;
    gMaxRedo = maxChannels - realChannels;
    fnDrawTickMark = drawTickMark;
    // nMaxChannels = maxChannels;

    gAnalPoolList = new AnalysisPool[maxChannels];
    if (NULL != gAnalPoolList)
    {
        gChannelOpened = new int32_t[gMaxChannels];
        if (NULL != gChannelOpened)
        {
            gChannelBusy = new int32_t[gMaxChannels];
            if (NULL != gChannelBusy)
            {
                // memset(tempBuffer, 0, sizeof(tempBuffer));
                // memset(&finddata, 0, sizeof(finddata));
                // if (_findfirst(aAnalysisDll, &finddata) != -1)
                // {
                //     Time = tempBuffer[2];
                //     localTm = localtime(&Time);
                //     year = localTm->tm_year - 100;
                //     mon = localTm->tm_mon + 1;
                //     day = localTm->tm_mday;
                //     sprintf(Buffer, "%02d.%02d.%02d", year, mon, day);
                // }
                snprintf(gTimeInfo, sizeof(gTimeInfo), "%s", Buffer);
                result = true;
            }
            else
            {
                delete[] gAnalPoolList;
                delete[] gChannelOpened;
                gAnalPoolList = NULL;
                gChannelOpened = NULL;
                gMaxRedo = 0;
                gMaxReal = 0;
                gMaxChannels = 0;
                result = false;
            }
        }
        else
        {
            delete[] gAnalPoolList;
            gAnalPoolList = NULL;
            gMaxRedo = 0;
            gMaxReal = 0;
            gMaxChannels = 0;
            result = false;
        }
    }
    else
    {
        gMaxRedo = 0;
        gMaxReal = 0;
        gMaxChannels = 0;
        result = false;
    }
    return result;
}

int32_t ExitAnalPool_()
{
    if (!gMaxChannels)
    {
        return 0;
    }
    if (gAnalPoolList)
    {
        delete[] gAnalPoolList;
    }
    if (gChannelOpened)
    {
        delete[] gChannelOpened;
    }
    if (gChannelBusy)
    {
        delete[] gChannelBusy;
    }
    gAnalPoolList = 0;
    gChannelOpened = 0;
    gChannelBusy = 0;
    gMaxRedo = 0;
    gMaxReal = 0;
    gMaxChannels = 0;
    return 1;
}
int32_t GetAnalPoolVolume_(int32_t *maxReal, int32_t *maxRedo)
{
    if (maxReal)
    {
        *maxReal = gMaxReal;
    }
    if (maxRedo)
    {
        *maxRedo = gMaxRedo;
    }
    return gMaxChannels;
}
int32_t OpenAnal_(int32_t chn, TSMPBAG *smpBag, TDLLIPINF *ipInf, TDLLEPINF *epInf, TDLLIDTINF *idtInf,
                  TDLLRESINF *resInf, TDLLSTDINF *stdInf)
{
    int32_t result;

    if (chn < gMaxChannels)
    {
        result = gAnalPoolList[chn].openAnal(smpBag, ipInf, epInf, idtInf, resInf, stdInf);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t CloseAnal_(int32_t chn)
{
    int32_t result;

    if (chn < gMaxChannels)
    {
        result = gAnalPoolList[chn].closeAnal();
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t StartAnal_(int32_t chn)
{
    int32_t result;

    if (chn < gMaxChannels)
    {
        result = gAnalPoolList[chn].startAnal();
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t __cdecl StopAnal_(int32_t chn)
{
    int32_t result;

    if (chn < gMaxChannels)
    {
        result = gAnalPoolList[chn].stopAnal();
    }
    else
    {
        result = false;
    }
    return result;
}
CODE ExecAnal_(int32_t chn)
{
    CODE result;

    if (chn < gMaxChannels)
    {
        result = gAnalPoolList[chn].execAnal();
    }
    else
    {
        result = ANAL_NOP;
    }
    return result;
}
int32_t GetAnalTime_(int32_t chn)
{
    int32_t result;

    if (chn < gMaxChannels)
    {
        result = gAnalPoolList[chn].getAnalTime();
    }
    else
    {
        result = 0;
    }
    return result;
}
char *GetErrMsg_(int32_t chn)
{
    if (chn == -1)
    {
        return Buffer;
    }
    if (chn == -2)
    {
        return gTimeInfo;
    }
    if (chn < gMaxChannels)
    {
        return gAnalPoolList[chn].getErrMsg();
    }
    return NULL;
}
int32_t MdyAnalStopTime_(int32_t chn, float stopTime)
{
    int32_t result;

    if (chn < gMaxChannels)
    {
        result = gAnalPoolList[chn].setStopTime(stopTime);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t MdyPeakSmpHead_(int32_t chn, int32_t *pSmpHead)
{
    int32_t result;

    if (chn < gMaxChannels)
    {
        result = gAnalPoolList[chn].setPeakSmpHead(pSmpHead);
    }
    else
    {
        result = 0;
    }
    return result;
}
int32_t TickAnal_(int32_t chn)
{
    AnalExecutor *pAnalExecutor;

    if (chn > gMaxChannels || !gAnalPoolList[chn].isOpened)
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (!pAnalExecutor)
    {
        return false;
    }
    pAnalExecutor->callbackDraw(chn);
    return true;
}
int32_t AnalOpened_(int32_t chn)
{
    int32_t result;

    if (chn < gMaxChannels)
    {
        result = gAnalPoolList[chn].isOpened;
    }
    else
    {
        result = 0;
    }
    return result;
}
int32_t AnalBusy_(int32_t chn)
{
    int32_t result;

    if (chn < gMaxChannels)
    {
        result = gAnalPoolList[chn].isStarted;
    }
    else
    {
        result = 0;
    }
    return result;
}
int32_t GetAnalOpened_(int32_t **chArray)
{
    int32_t openIdx;
    int32_t chn;

    chn = 0;
    openIdx = 0;
    while (chn <= gMaxChannels)
    {
        if (gAnalPoolList[chn].isOpened)
        {
            gChannelOpened[openIdx++] = chn;
        }
        ++chn;
    }
    *chArray = openIdx != 0 ? gChannelOpened : NULL;
    return openIdx;
}
int32_t GetAnalBusy_(int32_t **chArray)
{
    int32_t startIdx;
    int32_t chn;

    chn = 0;
    startIdx = 0;
    while (chn <= gMaxChannels)
    {
        if (gAnalPoolList[chn].isStarted)
        {
            gChannelBusy[startIdx++] = chn;
        }
        ++chn;
    }
    *chArray = startIdx != 0 ? gChannelBusy : NULL;
    return startIdx;
}
int32_t SetUkPkFactor_(int32_t chn, TUkPkFactor *lpUkPkFactor)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (chn > gMaxChannels || !gAnalPoolList[chn].isOpened)
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->setUkPkFactor(lpUkPkFactor);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t SetIdtTimeOfs_(int32_t chn, float fTimeOfs)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (chn > gMaxChannels || !gAnalPoolList[chn].isOpened)
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->setIdtTimeOfs(fTimeOfs);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t SetYMinUnit_(int32_t chn, double yMinUnit)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (chn > gMaxChannels || !gAnalPoolList[chn].isOpened)
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->setYMinUnit(yMinUnit);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t SetIdtQualitMode_(int32_t chn, int32_t nQualitMode, float fTimeWindow)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (chn > gMaxChannels || !gAnalPoolList[chn].isOpened)
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->setIdtQualitMode(nQualitMode, fTimeWindow);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t SetXMinUnitK_(int32_t chn, double xMinUnitK)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (chn > gMaxChannels || !gAnalPoolList[chn].isOpened)
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->setXMinUnitK(xMinUnitK);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t SetMiscellaneous_(int32_t chn, int64_t wParam, int64_t lParam)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (chn == -1)
    {
        if (lParam)
        {
            memcpy(Str1, (void *)lParam, 0x400u);
        }
        result = true;
    }
    else if (chn <= gMaxChannels && gAnalPoolList[chn].isOpened)
    {
        pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
        if (pAnalExecutor)
        {
            result = pAnalExecutor->setMiscellaneous((TMiscellaneous *)wParam, lParam);
        }
        else
        {
            result = false;
        }
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t EvalResult_(TDLLRESINF *resInf, TDLLEPINF *epInf, TDLLIDTINF *idtInf, TDLLMETRIC *metric)
{
    int32_t result;
    CGrpInfWrapper *pGrpInfTemp;
    CGrpInfWrapper *pGrpInf;
    CIdtInfWrapper idtInfWrapper;
    CEParaWrapper eParaWrapper;
    CResInfWrapper resInfWrapper;
    CConcCaculator c160Wrapper;

    resInfWrapper.init(resInf);
    eParaWrapper.init(epInf->epara);
    if (epInf->grpInf)
    {
        pGrpInfTemp = new CGrpInfWrapper();
        if (pGrpInfTemp)
        {
            pGrpInf = pGrpInfTemp->init((TDLLTPRGINF *)epInf->grpInf);
        }
        else
        {
            pGrpInf = NULL;
        }
    }
    else
    {
        pGrpInf = NULL;
    }
    idtInfWrapper.init(idtInf);
    c160Wrapper.init(&resInfWrapper, &eParaWrapper, pGrpInf, &idtInfWrapper, NULL);
    result = c160Wrapper.setMetric(metric, 0);
    idtInfWrapper.close();
    eParaWrapper.close();
    resInfWrapper.close_();
    return result;
}
int32_t EvalColumnPerfEx_(TDLLResultListItem *pHead, int32_t pCount, int32_t *smpHead, float freq, double xMinUnitK)
{
    int32_t i;

    if (!pHead || !smpHead)
    {
        return 0;
    }
    for (i = 0; i < pCount; ++i)
    {
        calcW50etc(pHead, pHead, smpHead, freq, xMinUnitK);
        memset((void *)&pHead->fts, 0, 4u);
        memset((void *)&pHead->fte, 0, 4u);
        memset((void *)&pHead->ReserveX, 0, 4u);
    }
    return 1;
}
double EvalKHeightWEx_(TDLLResultListItem *pHead, int32_t *smpHead, double k, float freq, double xMinUnitK,
                       double *lpWL, double *lpWR)
{
    double dWL = 0;
    double dWR = 0;

    _EvalKHeightWEx(pHead, smpHead, k, freq, xMinUnitK, &dWL, &dWR);
    if (lpWL)
    {
        *lpWL = dWL;
    }
    if (lpWR)
    {
        *lpWR = dWR;
    }
    return dWL + dWR;
}
int32_t EvalColumnPerf_(TDLLResultListItem *pHead, int32_t pCount, int32_t *smpHead, float freq)
{
    return EvalColumnPerfEx_(pHead, pCount, smpHead, freq, 60.0);
}
int32_t EvalColumnPerfEx_(TDLLResultListItem *pHead, int32_t pCount, int32_t *smpHead, float freq, float time)
{
    int32_t i;

    if (!pHead || !smpHead)
    {
        return false;
    }
    for (i = 0; i < pCount; ++i)
    {
        calcW50etc(pHead, pHead, smpHead, freq, time);
        memset((void *)&pHead->fts, 0, 4u);
        memset((void *)&pHead->fte, 0, 4u);
        memset((void *)&pHead->ReserveX, 0, 4u);
    }
    return true;
}
double EvalKHeightW_(TDLLResultListItem *pHead, int32_t *smpHead, double k, float freq, double *lpWL, double *lpWR)
{
    return EvalKHeightWEx_(pHead, smpHead, k, freq, 60.0, lpWL, lpWR);
}
int32_t EvalGroup_(TDLLGRPINF *grpInf, TDLLRESINF *resInf)
{
    TDLLResultListItem *pDLLResult;
    int32_t num;
    int32_t result;
    CGrpInfWrapper grpInfWrapper;
    CResInfWrapper resInfWrapper;

    grpInfWrapper.init((TDLLTPRGINF *)grpInf);
    resInfWrapper.init(resInf);
    num = resInfWrapper.getNum();
    pDLLResult = (TDLLResultListItem *)resInfWrapper.head;
    result = grpInfWrapper.calcGroupAggregate(pDLLResult, num);
    resInfWrapper.close_();
    grpInfWrapper.close_();
    return result;
}
//// no caller
int32_t EvalGroupResult_(TDLLGROUPListItemMerged *pItem, TDLLGRPINF *pGrpInf)
{
    int32_t num;
    int32_t k;
    int32_t i;
    int32_t j;

    num = *pGrpInf->num;
    if (!num)
    {
        return 0;
    }
    for (i = 0; i < num; ++i)
    {
        strncpy((char *)pItem[i].Name, (const char *)pGrpInf->head[i].Name, sizeof(pItem[i].Name));
        pItem[i].Area = pGrpInf->head[i].Area;
        pItem[i].Height = pGrpInf->head[i].Height;
        pItem[i].AreaPer = pGrpInf->head[i].AreaPer;
        pItem[i].Conc = pGrpInf->head[i].Conc;
    }
    for (j = 0; j < num; ++j)
    {
        for (k = j + 1; k < num; ++k)
        {
            if (!strcmp((const char *)pItem[k].Name, (const char *)pItem[j].Name))
            {
                pItem[j].Area += pItem[k].Area;
                pItem[j].Height += pItem[k].Height;
                pItem[j].AreaPer += pItem[k].AreaPer;
                pItem[j].Conc += pItem[k].Conc;
                if (k >= num - 1)
                {
                    memset((void *)&pItem[k], 0, sizeof(TDLLGROUPListItemMerged));
                }
                else
                {
                    memcpy((void *)&pItem[k], (const void *)&pItem[k + 1],
                           (num - 1 - k) * sizeof(TDLLGROUPListItemMerged));
                }
                --num;
            }
        }
    }
    return num;
}

int32_t EvalCalibFact_(TDLLSTDINF *stdInf, TEPara *epara, TDLLIDTINF *idtInf)
{
    int32_t result;
    CStdInfManager stdInfWrapper;
    CAmtInfWrapper amtInfWrapper;
    CIdtInfWrapper idtInfWrapper;
    CCptInfWrapper cptInfWrapper;
    CEParaWrapper eParaWrapper;

    amtInfWrapper.init(stdInf->amtInf);
    cptInfWrapper.init(stdInf->cptInf);
    eParaWrapper.init(epara);
    idtInfWrapper.init(idtInf);
    stdInfWrapper.init(&amtInfWrapper, &cptInfWrapper, &eParaWrapper, &idtInfWrapper, stdInf->CurveType,
                       stdInf->Zero);
    result = stdInfWrapper.calcMethodValueAndWeightAll();
    stdInfWrapper.close();
    idtInfWrapper.close();
    eParaWrapper.close();
    cptInfWrapper.close_();
    amtInfWrapper.close();
    return result;
}
int32_t ManualPeakStart_(int32_t chn, float startTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->handlePeakStart(startTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualPeakEnd_(int32_t chn, float endTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->handlePeakEnd(endTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualPeakMoveSplit_(int32_t chn, float valleyTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->handlePeakMoveSplit(valleyTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualPeakAddSplit_(int32_t chn, float splitTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->handlePeakAddSplit(splitTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualPeakDelSplit_(int32_t chn, float splitTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->handlePeakDelSplit(splitTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualPeakAddOnlyOne_(int32_t chn, float beginTime, float endTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->handlePeakAddOnlyOne(beginTime, endTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualPeakDelete_(int32_t chn, float beginTime, float endTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->handlePeakDelete(beginTime, endTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualBaseValley_(int32_t chn, float beginTime, float endTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->handleBaseValley(beginTime, endTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualBaseTogether_(int32_t chn, float beginTime, float endTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->handleBaseTogether_(beginTime, endTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualBaseTailTangent_(int32_t chn, float beginTime, float endTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->handleBaseTailTangent(beginTime, endTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualBaseFrontTangent_(int32_t chn, float beginTime, float endTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->handleBaseFrontTangent(beginTime, endTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualBaseForwHori_(int32_t chn, float beginTime, float endTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->checkPeakAndCalcMetricV3(beginTime, endTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualBaseBackHori_(int32_t chn, float beginTime, float endTime)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->checkPeakAndCalcMetricV4(beginTime, endTime, 1);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualParaWidth_(int32_t chn, float beginTime, float endTime, float pkWidth)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->checkPeakAndCalcMetricV2(beginTime, endTime, pkWidth, 0);
    }
    else
    {
        result = false;
    }
    return result;
}
int32_t ManualParaNoise_(int32_t chn, float beginTime, float endTime, float pkNoise)
{
    int32_t result;
    AnalExecutor *pAnalExecutor;

    if (!isValidChannel(chn))
    {
        return false;
    }
    pAnalExecutor = gAnalPoolList[chn].pAnalExecutor;
    if (pAnalExecutor)
    {
        result = pAnalExecutor->checkPeakAndCalcMetricV1(beginTime, endTime, pkNoise, 0);
    }
    else
    {
        result = false;
    }
    return result;
}
double CvtConcToAmt_(double conc, TDLLMETRIC *metric, int32_t method)
{
    double result;

    if (method && method != 1)
    {
        result = calcAmtMValue((TSTDAMTListItem *)metric, method) * conc;
    }
    else
    {
        result = conc;
    }
    return result;
}
double CvtConcToAmtByIstd_(double conc, TDLLMETRIC *metric)
{
    return calcAmtMValue((TSTDAMTListItem *)metric, 2) * conc;
}
int32_t LearnAutoPara_(AUTOPOOL *autoPool, float freq, AUTOPARA *autoPara)
{
    int32_t result;

    result = LearnAutoIPara_(autoPool, freq, &gLearnIPara);
    autoPara->pkWidth = (float)(gLearnIPara.width * 3.0 / (10.0 * freq));
    autoPara->pkNoise = (int32_t)(gLearnIPara.noise * 10.0);
    autoPara->pkDrift = gLearnIPara.drift * freq;
    return result;
}
int32_t MakeAutoPara_(int32_t *buf, int32_t len, float freq, AUTOPARA *autoPara)
{
    int32_t result;

    result = MakeAutoIPara_(buf, len, freq, &gMakeIPara);
    autoPara->pkWidth = (float)(gMakeIPara.width * 3.0 / (10.0 * freq));
    autoPara->pkNoise = (int32_t)(gMakeIPara.noise * 10.0);
    autoPara->pkDrift = gMakeIPara.drift * freq;
    return result;
}
int32_t LearnAutoIPara_(AUTOPOOL *autoPool, float freq, AUTOIPARA *autoIPara)
{
    int32_t len;
    int32_t i;
    int32_t result;
    int32_t residue;
    int32_t *piSource;

    if (!autoPool || !autoIPara || freq <= 0)
    {
        return false;
    }
    if (!autoPool->cnt && !autoPool->ovr)
    {
        return false;
    }
    if (autoPool->ovr)
    {
        residue = (autoPool->cnt + 1) % autoPool->len;
        len = autoPool->len;
    }
    else
    {
        residue = 0;
        len = autoPool->cnt;
    }
    piSource = new int32_t[len];
    for (i = 0; i < len; ++i)
    {
        piSource[i] = autoPool->buf[(i + residue) % autoPool->len];
    }
    result = MakeAutoIPara_(piSource, len, freq, autoIPara);
    delete[] piSource;
    return result;
}
int32_t MakeAutoIPara_(int32_t *buf, int32_t len, float freq, AUTOIPARA *autoIPara)
{
    int32_t result;
    float drift;
    float noise;
    float freqD10;
    int32_t n;

    if (!buf || !autoIPara)
    {
        return false;
    }
    n = len - 1;
    if (n >= 5 && freq > 0)
    {
        noise = (float)(calcNoise(buf, n, 4));
        drift = 0.0;
        if (n >= 6)
        {
            drift = (float)((buf[n - 3] - buf[2]) / (n - 5));
            if (drift < 0.0)
            {
                drift = (float)(0.0 - drift);
            }
        }
        freqD10 = (float)(freq / 10.0 + 0.5);
        if (freqD10 < 2)
        {
            freqD10 = 2;
        }
        autoIPara->width = (int32_t)freqD10;
        autoIPara->noise = (float)(noise / 10.0);
        autoIPara->drift = drift;
        result = true;
    }
    else
    {
        autoIPara->width = 0;
        autoIPara->noise = 0;
        autoIPara->drift = 0;
        result = false;
    }
    return result;
}

// sub_1001956B
int32_t calcNoise(int32_t *data, int32_t tail, int32_t chn)
{
    int32_t i;
    int32_t n;
    int32_t *pData;
    float avg;
    float delta;
    float deltaMax;
    float deltaMin;
    int32_t deltaDiffMax;

    if (tail < chn + 1)
    {
        return 0;
    }
    pData = (int32_t *)new int32_t[chn + 1];
    memset(pData, 0, sizeof(int32_t) * (chn + 1));
    memcpy(pData, data, sizeof(int32_t) * (chn + 1));
    deltaDiffMax = 0;
    n = chn + 1;
    do
    {
        deltaMin = 0.0;
        deltaMax = 0.0;
        for (i = 0; i <= chn; ++i)
        {
            avg = (float)((double)(pData[chn] - pData[0]) / (double)chn);
            delta = (float)((double)pData[i] - (double)i * avg - (double)pData[0]);
            if (delta <= (double)deltaMin)
            {
                deltaMin = (float)((double)pData[i] - (double)i * avg - (double)pData[0]);
            }
            if (delta >= (double)deltaMax)
            {
                deltaMax = (float)((double)pData[i] - (double)i * avg - (double)pData[0]);
            }
        }
        if ((int32_t)(deltaMax - deltaMin) > deltaDiffMax)
        {
            deltaDiffMax = (int32_t)(deltaMax - deltaMin);
        }
        memcpy(pData, pData + 1, sizeof(int32_t) * chn);
        pData[chn] = data[n++];
    } while (n < tail);
    delete[] pData;
    return deltaDiffMax;
}
